#ifdef WIN32
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#endif

#ifdef LINUX
#include "./GL/gl.h"
//#include <GL/glew.h>
#include "./GL/glut.h"
#include "./GL/glu.h"
#endif

//using namespace std;

#define WINDOW_TITLE_ "Scene View --SHADED--"
void processKeys( unsigned char key, int x, int y);
//void processMouse( int button, int state, int x, int y );
void display(void);
void idle(void);
void reshape(int w, int h);

GLfloat light_pos[] = { 0.0, 2.0, 2.0, 0.0 };

void init() {
	glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
	glEnable( GL_LIGHTING );
	glEnable( GL_LIGHT0 );
}

GLfloat angle = 0.0;

void drawYZGrid( float x, int nx, float z, int nz ) {
	float dx = x/(float)nx;
	float dz = z/(float)nz;
	float X = -1*x/2.0;
	float Z = -1*z/2.0;
	for( ; X<=x/2.0; X+=dx ) {
		Z = -1*z/2.0;
		glBegin(GL_LINES);
		glVertex3f( X, 0, Z );
		glVertex3f( X, 0, Z+z );
		glEnd();
	}
	X = -1*x/2.0;
	Z = -1*z/2.0;
	for( ; Z<=z/2; Z+=dz ) {
		glBegin(GL_LINES);
		glVertex3f( X, 0, Z );
		glVertex3f( X+x, 0, Z );
		glEnd();
	}
	
}

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
	
 	glutInitWindowSize( 700, 700 );
	glutInitWindowPosition( 0, 0 );
	glutCreateWindow( WINDOW_TITLE_ );

	glShadeModel( GL_SMOOTH );
	glEnable( GL_DEPTH_TEST );
	init();
	
	glutDisplayFunc( display);
	glutIdleFunc( idle);
	glutReshapeFunc( reshape);
	
	glutKeyboardFunc( processKeys);

	glutMainLoop();

	return 0;
}


void display(void) {	
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glPushMatrix();
	glLoadIdentity();
	/* clear the matrix */
	/* viewing transformation */
	gluLookAt(5.0, 5.0, 9.0,
				 0.0, 0.0, 0.0,
				 0.0, 1.0, 0.0);

	/*
	glPushMatrix();
	glColor3f(0.2, 0.2, 0.2);
	glTranslatef( 0.0, -1.1, 0.0);
	glBegin(GL_TRIANGLE_STRIP);
	glVertex3f(-3, 0, 3);
	glVertex3f( 3, 0, 3);
	glVertex3f(-3, 0, -3);
	glVertex3f( 3, 0, -3);
	glEnd();
	glPopMatrix();
	*/

	glDisable( GL_LIGHTING );
	
	glPushMatrix();
	glColor3f( 0.2, 0.2, 0.2);
	glTranslatef( 0.0, -2.0, 0.0);
	drawYZGrid(10, 10, 10, 10);
	glPopMatrix();

	glPushMatrix();
	glTranslatef( 0.0, 0.0, 0.0 );
	glColor3f(1.0, 1.0, 1.0);
	glutWireCube(4.0);
	glPopMatrix();
	
	glPushMatrix();
	glColor3f( 1.0, 1.0, 1.0 );
	glTranslatef( light_pos[0], light_pos[1], light_pos[2] );
	//glutSolidSphere(1.2, 20, 20 );
	glColor3f( 0.9, 0.9, 0.9 );
	glutWireSphere( 0.2, 20, 20 );
	glPopMatrix();

	glEnable( GL_LIGHTING);
	
	//--------------------------------------
	//--Rotation transformation-------------
	//--------------------------------------
	glPushMatrix();
	glRotatef(angle, 0.0, 1.0, 0.0 );
	
	glPushMatrix();
	glColor3f( 0.6, 0.2, 0.4);
	glTranslatef( 0.5, -0.25, 0.5 );
	glutSolidCube(1.5);
	glPopMatrix();

	glPushMatrix();
	glColor3f( 0.5, 0.7, 0.8);
	glTranslatef( -1.0, -0.0, -0.25 );
	glutSolidCube(1.0);
	glPopMatrix();

	glPopMatrix();
	
	glPopMatrix();
	//glutSwapBuffers();
	glFlush();
}

void animate () {
	angle += 0.02;
	if(angle >360.0) angle = 0.0;
}

void idle(void) {
	animate();
	static int lastUpdate = 0;
	static int frames = 0;
	char buf[20];

	glutPostRedisplay(); // calls your display callback function
	glutSwapBuffers();

	int currentTime = glutGet( GLUT_ELAPSED_TIME );
	
	frames++;

	// is the time difference between lastUpdate and current time > one second ( 1000 ms )?
	if ( ( currentTime - lastUpdate ) >= 1000 ){
		//sprintf( buf, "FPS: %d", frames );
		std::cout <<"FPS: "<<frames;
		frames = 0;
		lastUpdate = currentTime;

	}

	// you could also put a sleep here, to avoid glut consuming full processor time
	// relaxing things
	
	Sleep(1);
}

/* modeling transformation */
void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1.0, 1.0, -1.0, 1.0, 2.5, 200.0);
	//gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);j
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void processKeys(unsigned char key, int x, int y) {
	
	if (key == 27)
		exit(0);
}
